package org.jeecg.common.util.picutil;

import cn.hutool.core.io.FileUtil;
import lombok.SneakyThrows;
import net.coobird.thumbnailator.Thumbnails;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDate;
import java.util.Optional;
import javax.imageio.ImageIO;

public class ImageUtils {

    public static void main(String[] args) {
        String imgUrl = "https://n.sinaimg.cn/sinacn12/733/w1400h933/20180410/ab8a-fyvtmxe9278329.jpg";
        String outPath = "/Users/zjarlin/Desktop/test.png";
        addTextWaterMark(imgUrl, outPath, LocalDate.now().toString(), Position.BOTTOM_RIGHT);
    }

    /**
     * 添加文字水印
     *
     * @param imgUrl   img url
     * @param outPath  出路径
     * @param text     文本
     * @param position 位置枚举
     * @author zjarlin
     * @since 2023/03/22
     */
    public static void addTextWaterMark(String imgUrl, String outPath, String text, Position position) {
        try {
            URL url = new URL(imgUrl);
            BufferedImage image = ImageIO.read(url);

            Graphics2D graphics2D = image.createGraphics();
            graphics2D.setPaint(Color.RED);//水印文字的颜色
            graphics2D.setFont(new Font("微软雅黑", Font.PLAIN, 18));//设置字体以及字体大小，可以根据需要调整
            graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);//抗锯齿
            graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1f));//设置透明度

            int x = 0, y = 0;
            int margin = 40;//文字与图片边缘的距离
            switch (position) {
                case TOP_LEFT://左上
                    x = margin;
                    y = margin + graphics2D.getFontMetrics().getHeight();
                    break;
                case TOP_RIGHT://右上
                    x = image.getWidth() - graphics2D.getFontMetrics().stringWidth(text) - margin;
                    y = margin + graphics2D.getFontMetrics().getHeight();
                    break;
                case BOTTOM_LEFT://左下
                    x = margin;
                    y = image.getHeight() - margin;
                    break;
                case BOTTOM_RIGHT://右下
                    x = image.getWidth() - graphics2D.getFontMetrics().stringWidth(text) - margin;
                    y = image.getHeight() - margin;
                    break;
                default:
                    break;
            }
            graphics2D.drawString(text, x, y);//添加水印文本
            graphics2D.dispose();

            File outFile = new File(outPath);//输出文件路径
            ImageIO.write(image, "png", outFile);//输出文件
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 给网络图片加文字水印
     *
     * @param imgUrl  图片url
     * @param outPath 输出文件路径
     * @param text
     */
    public static void addTextWaterMark(String imgUrl, String outPath, final String text) {
        try {
            URL url = new URL(imgUrl);
            BufferedImage image = ImageIO.read(url);

            Graphics2D graphics2D = image.createGraphics();
            graphics2D.setPaint(Color.RED);//水印文字的颜色
            graphics2D.setFont(new Font("微软雅黑", Font.PLAIN, 18));//设置字体以及字体大小

            graphics2D.drawString(text, image.getWidth() - 500, image.getHeight() - 100);//绘制文本水印

            File outFile = new File(outPath);//输出文件路径
            ImageIO.write(image, "png", outFile);//输出文件
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public enum Position {
        TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT
    }
    /**
     * @param srcPath   原图片地址
     * @param desPath   目标图片地址
     * @param limitSize 指定图片大小上限,单位kb
     * @param accuracy  精度,递归压缩的比率,建议小于0.9
     * @return desPath
     */
    public static String commpressPicForScale(String srcPath, String desPath, int limitSize, double accuracy) {
        accuracy = Optional.ofNullable(accuracy).orElse(0.9);
        File srcFile = new File(srcPath);
        long srcFilesize = srcFile.length() / 1024;
        System.out.println("原图片:" + srcPath + ",大小:" + srcFilesize + "kb");
        //递归压缩,直到目标文件大小小于desFileSize
        File desFile = FileUtil.copy(srcPath, desPath, false);
        long desFileSize = desFile.length() / 1024;

        commpressPicCycle(desPath, desFileSize, limitSize, accuracy);
        File file = new File(desPath);
        long tarFileSize = file.length() / 1024;

        System.out.println("目标图片:" + desPath + ",大小" + tarFileSize + "kb");
        System.out.println("图片压缩完成!");
        return desPath;
    }

    @SneakyThrows
    public static void commpressPicCycle(String desPath, long desFileSize, final int limitSize, double accuracy) {
        File imgFile = new File(desPath);

        long fileSize = imgFile.length() / 1024;
        //判断大小,如果小于500k,不压缩,如果大于等于500k,压缩
        if (fileSize <= limitSize) {return;}
        //计算宽高
        BufferedImage bim = ImageIO.read(imgFile);
        int imgWidth = bim.getWidth();
        int imgHeight = bim.getHeight();
        int desWidth = new BigDecimal(imgWidth).multiply(BigDecimal.valueOf(accuracy)).intValue();
        int desHeight = new BigDecimal(imgHeight).multiply(BigDecimal.valueOf(accuracy)).intValue();
        Thumbnails.of(desPath).size(desWidth, desHeight).outputQuality(accuracy).toFile(desPath);
        //如果不满足要求,递归直至满足小于1M的要求
        commpressPicCycle(desPath, desFileSize, limitSize, accuracy);
    }

    @SneakyThrows
    public static byte[] url2byte(String sysFaceUrl) {
        File file = UrltoFile(sysFaceUrl);
        return FileTobyte(file);
    }

    //将Url转换为File
    public static File UrltoFile(String url) throws Exception {
        HttpURLConnection httpUrl = (HttpURLConnection)new URL(url).openConnection();
        httpUrl.connect();
        InputStream ins = httpUrl.getInputStream();
        File file = new File(
                System.getProperty("java.io.tmpdir") + File.separator + "xia");//System.getProperty("java.io.tmpdir")缓存
        if (file.exists()) {
            file.delete();//如果缓存中存在该文件就删除
        }
        OutputStream os = new FileOutputStream(file);
        int bytesRead;
        int len = 8192;
        byte[] buffer = new byte[len];
        while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        ins.close();
        return file;

    }

    //将File对象转换为byte[]的形式
    public static byte[] FileTobyte(File file) {
        FileInputStream fileInputStream = null;
        byte[] imgData = null;

        try {

            imgData = new byte[(int)file.length()];

            //read file into bytes[]
            fileInputStream = new FileInputStream(file);
            fileInputStream.read(imgData);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return imgData;
    }











}
